﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.ComponentModel;
using System.Drawing;
using System.IO;

using mKoenig.PictureSlide.Properties;

namespace mKoenig.PictureSlide
{
  public class FileHandling
  {
    private static FileHandling instance = new FileHandling();
    public static FileHandling GetInstance()
    {
      return instance;
    }

    private Settings setting = Settings.Default;
    public List<string> myPictureFiles = new List<string>();

    private BackgroundWorker worker = new BackgroundWorker();

    Object thisLock = new Object();

    private FileHandling()
    {
      if (setting.PicturePath == string.Empty) setting.PicturePath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
      if (Directory.Exists(setting.PicturePath))
      {
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        worker.RunWorkerAsync();
      }
    }

    public Render.ImageData LoadImage(int ActualPicture, Size TargetSize)
    {
      lock (thisLock)
      {
        Image tmp = null;
        Render.ImageData result = new Render.ImageData();

        result.Image = Image.FromStream(Render.GetEmbeddedResourceStream("mKoenig.PictureSlide.nopic.jpg"));
        if (ActualPicture < myPictureFiles.Count)
        {
          // try to load
          try
          {
            result.Name = Path.GetFileName(myPictureFiles[ActualPicture]);
            result.Image = Image.FromFile(myPictureFiles[ActualPicture]);

            result.Date = File.GetCreationTime(myPictureFiles[ActualPicture]).ToShortDateString() + " " + File.GetCreationTime(myPictureFiles[ActualPicture]).ToShortTimeString() + " (file)";
            for (int i = 0; i < result.Image.PropertyIdList.Length; i++)
            {
              System.Drawing.Imaging.PropertyItem item = result.Image.PropertyItems[i];
              if (item.Id == 36867) // 0x9003 orginal Time
              {
                string myDate = System.Text.Encoding.ASCII.GetString(item.Value);
                myDate = myDate.Replace("\0", "");
                result.Date = myDate + " (original Date)";
              }
            }
          }
          catch
          {
            Graphics g = Graphics.FromImage(result.Image);
            SolidBrush drawBrush = new SolidBrush(Color.OrangeRed);

            g.DrawString("Error loading " + result.Name, new Font("Arial", 10.0f), drawBrush, new PointF(50.0f, (float)(result.Image.Height / 2) - 10.0f));
            g.Dispose();
          }
        }

        // try to resize
        try
        {
          result.Image = Resizer.ResizeImage(result.Image, new Size(TargetSize.Width, TargetSize.Height));
        }
        catch
        {
          tmp = Image.FromStream(Render.GetEmbeddedResourceStream("MkSlide.nopic.jpg"));
          result.Image = Resizer.ResizeImage(tmp, new Size(TargetSize.Width, TargetSize.Height));
        }

        tmp = null;
        return result;
      }  
    }

    public void Add(string FileName)
    {
      myPictureFiles.Add(FileName);
    }

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
      Console.WriteLine(DateTime.Now.ToLongTimeString() + ": Start scan directory");

      string[] rootfiles = Directory.GetFiles(setting.PicturePath, "*.jpg", SearchOption.TopDirectoryOnly);
      foreach (string aFile in rootfiles)
      {
        if (this.Count <= maxFiles)
          this.Add(aFile);
        else
          break;
      }
      DirSearch(setting.PicturePath);
    }
    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {

      Console.WriteLine(DateTime.Now.ToLongTimeString() + ": Finished scan directory. Items " + this.Count.ToString());
    }

    private void DirSearch(string sDir)
    {
      string[] dirs = Directory.GetDirectories(sDir);

      foreach (string d in dirs)
      {
        string[] files = Directory.GetFiles(d, "*.jpg");
        MyStringComparer cmp = new MyStringComparer();
        Array.Sort(files, cmp);

        foreach (string f in files)
        {
          if (this.Count < maxFiles)
            this.Add(f);
          else
            break;
        }
        DirSearch(d);
      }
    }
    private class MyStringComparer : IComparer<string>
    {
      public int Compare(string x, string y)
      {
        if (x == null)
        {
          if (y == null)
          {
            // If x is null and y is null, they're
            // equal. 
            return 0;
          }
          else
          {
            // If x is null and y is not null, y
            // is greater. 
            return -1;
          }
        }
        else
        {
          // If x is not null...
          //
          if (y == null)
          // ...and y is null, x is greater.
          {
            return 1;
          }
          else
          {

            // ...and y is not null, compare the 
            // lengths of the two strings.
            //
            int retval = x.Length.CompareTo(y.Length);

            if (retval != 0)
            {
              // If the strings are not of equal length,
              // the longer string is greater.
              //
              return retval;
            }
            else
            {
              // If the strings are of equal length,
              // sort them with ordinary string comparison.
              //
              return x.CompareTo(y);
            }
          }
        }
      }
    }

    private static int maxFiles = 30000;
    public int MaxFiles
    {
      get
      {
        return maxFiles;
      }
      set
      {
        maxFiles = value;
      }
    }
    public int Count
    {
      get
      {
        return myPictureFiles.Count;
      }
    }
  }
}
